﻿using System;
using System.Collections.Generic;

namespace SharpML.Api.Extensions
{
    public static class Linqs
    {
        /// <summary>
        /// Just like Take, only from the end of the collection.  Will cause a full iteration.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public static IEnumerable<T> TakeLast<T>( this IEnumerable<T> source, int count )
        {
            // Contract
            if( source == null ) 
                throw new ArgumentNullException( "source" );

            // Sanity check
            if( count == 0 ) 
                yield break;

            // Create a new container to hold the results
            T[] result = new T[count];

            // Locals
            int index = 0;
            int sourceCount = 0;

            // Iterate the source collection into the container, will worry about order later
            // This must be done this way because we don't want to back with an array
            // the actual size of source, incase it's huge, so just count 'em and store references.
            foreach( T element in source )
            {
                // Store item
                result[index] = element;

                // Set new index
                index = ( index + 1 ) % count;

                // Count them
                sourceCount++;
            }

            // Not enough items?
            if( sourceCount < count )
            {
                // The count is how many we actually have
                count = sourceCount;

                // Start at index 0
                index = 0;
            }

            // Yield each result for linq 
            for( int offset = 0; offset < count; ++offset )
                yield return result[( index + offset ) % count];
        }
    }
}
